#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time   : 2021/7/9 22:32
# @Author : cjw
from typing import Optional

from fastapi import APIRouter, Depends, Header, HTTPException, status

app05 = APIRouter()

"""创建、导入和声明依赖"""


async def common_parameters(q: Optional[str] = None, page: int = 1, limit: int = 100):
	return {'q': q, 'page': page, 'limit': limit}


@app05.get('/dependency01', summary='异步接口使用异步依赖')
async def dependency01(commons: dict = Depends(common_parameters)):
	return commons


@app05.get('/dependency02', summary='同步接口使用异步依赖')
def dependency02(commons: dict = Depends(common_parameters)):
	return commons


"""类作为依赖项"""
fake_items_db = [{'item_name': 'Foo'}, {'item_name': 'Bar'}, {'item_name': 'Baz'}]


class CommonQueryParams:

	def __init__(self, q: Optional[str] = None, page: int = 1, limit: int = 100):
		self.q = q
		self.page = page
		self.limit = limit


@app05.get('/class_as_dependency_1', summary='类作为依赖项, 写法1')
def class_as_dependency_1(commons: CommonQueryParams = Depends(CommonQueryParams)):
	return commons


@app05.get('/class_as_dependency_2', summary='类作为依赖项, 写法2')
def class_as_dependency_2(commons: CommonQueryParams = Depends()):
	return commons


@app05.get('/class_as_dependency_3', summary='类作为依赖项, 写法3')
def class_as_dependency_3(commons=Depends(CommonQueryParams)):
	# 这种写法没有类型提示
	response = {}
	if commons.q:
		response.update({'q': commons.q})
	items = fake_items_db[commons.page:commons.page + commons.limit]
	response.update({'items': items})
	return response


"""子依赖"""


def query(q: Optional[str] = None):
	return q


def sub_query(q: str = Depends(query), last_query: Optional[str] = None):
	if not q:
		return last_query
	return q


@app05.get('/sub_dependency', summary='子依赖')
def sub_dependency(final_query: str = Depends(sub_query, use_cache=True)):
	# use_cache=True: 表示当多个依赖有一个共同的子依赖，每次request请求只会调用子依赖一次，多次调用将从缓存中获取
	return {'sub_dependency': final_query}


"""路径操作装饰器中的多依赖"""


async def verify_token(x_token: str = Header(...)):
	"""没有返回值的子依赖"""
	if x_token != 'fake-super-secret-token':
		raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST,
		                    detail='X-Token header invalid')
	return x_token


async def verify_key(x_key: str = Header(...)):
	"""有返回值的子依赖, 但是返回值不会被调用"""
	if x_key != 'fake-super-secret-key':
		raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST,
		                    detail='X-Key header invalid')
	return x_key


@app05.get('/dependency_in_path_operation',
           dependencies=[Depends(verify_token), Depends(verify_key)],
           summary='路径操作装饰器中的多依赖')
async def dependency_in_path_operation():
	return [{'user': 'user01'}, {'user': 'user02'}]


"""全局依赖"""

# app05 = APIRouter(dependencies=[Depends(verify_token), Depends(verify_key)])


"""待yield的依赖"""


# python 3.7 才支持
# 以下是伪代码
async def get_db():
	db = 'db_connection'
	try:
		yield db
	finally:
		db.endswith('db_close')


async def dependency_a():
	dep_a = 'generate_dep_a()'
	try:
		yield dep_a
	finally:
		dep_a.endswith('db_close')


async def dependency_b(dep_a=Depends(dependency_a)):
	dep_b = 'generate_dep_b()'
	try:
		yield dep_b
	finally:
		dep_b.endswith(dep_a)


async def dependency_c(dep_b=Depends(dependency_b)):
	dep_c = 'generate_dep_c()'
	try:
		yield dep_c
	finally:
		dep_c.endswith(dep_b)
